from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
# Create your views here.
class CarouselView(APIView):
    def get(self,request):
        car_data = Carousel.objects.all()
        # car_data不能直接返回，手动序列化为car_list
        car_list = []
        for i in car_data:
            car_list.append({
                'id':i.id,
                'imgPath':i.imgPath,
                'describes':i.describes,
            })
        return Response({
            'code':200,
            'car':car_list
        })

class OneCate(APIView):
    def post(self,request):
        # 1.提取类别信息
        cate_name = request.data.get('categoryName')
        # 2.根据类别名，查询类别
        try:
            cate_data = Category.objects.get(cate_name=cate_name)
        except Exception as e:
            print(e)
            return Response({'code':400,'msg':'类别不存在'})
        # 3.根据类别 查询 对应的商品信息
        # goods_data = Goods.objects.filter(cate=cate_data)        #写法1
        # goods_data = Goods.objects.filter(cate_id=cate_data.id)  #写法2
        goods_data = cate_data.goods_set.all()                   #写法3
        # 4.手动实现序列化
        goods_list = []
        for i in goods_data:
            goods_list.append({
                'id':i.id,
                'sku_name':i.sku_name,
                'price':i.price,
                'selling_price':i.selling_price,
                'img':i.img,
                'title':i.title,
                'instruction':i.instruction,
                'count':i.count,
                'stock':i.stock,
                'cate':i.cate_id
            })
        return Response({'code':200,'goods':goods_list})

from functools import reduce  #导入高阶函数
class HostGoods(APIView):
    def post(self,request):
        # 1.获取热门商品 列表
        hot_cates = request.data.get('categoryName')
        # 2.根据热门商品列表 获取热门商品种类对象
        hot_cates_list = []
        for i in hot_cates:
            hot_cates_list.append(
                Category.objects.get(cate_name=i)
            )
        # 得到的结果 hot_cates_list = [电视类别ORM对象，空调类别ORM对象，洗衣机类别ORM对象]
        # 3.根据hot_cates_list获取对应的热门商品休息
        hot_goods_list = []
        for i in hot_cates_list:
            hot_goods_list.append(i.goods_set.all())
        # 得到的结果：hot_goods_list = [[所有的电视ORM对象]，[所有的空调ORM对象]，[所有的洗衣机ORM对象]]
        # 4.将3个列表 拼接为1个列表
        hot_data = reduce(lambda x,y:x|y,hot_goods_list).order_by('count')
        # 得到的结果为：hot_data = [所有的电视ORM对象,所有的空调ORM对象,所有的洗衣机ORM对象]
        # 5.序列化结果
        goods_list = []
        for i in hot_data:
            goods_list.append({
                'id': i.id,
                'sku_name': i.sku_name,
                'price': i.price,
                'selling_price': i.selling_price,
                'img': i.img,
                'title': i.title,
                'instruction': i.instruction,
                'count': i.count,
                'stock': i.stock,
                'cate': i.cate_id
            })
        return Response({'code': 200, 'goods': goods_list})

class OneGood(APIView):
    # 获取一个商品的详情，动态参数id：商品id
    def get(self,request,id):
        try:
            good_data = Goods.objects.get(id=id)
        except Exception as e:
            print(e)
            return Response({'code': 400, 'msg': '商品不存在'})
        # 商品存在 返回成功的响应
        return Response({
            'code':200,
            'msg':'查询成功',
            'goods':{
                'id': good_data.id,
                'sku_name': good_data.sku_name,
                'price': good_data.price,
                'selling_price': good_data.selling_price,
                'img': good_data.img,
                'title': good_data.title,
                'instruction': good_data.instruction,
                'count': good_data.count,
                'stock': good_data.stock,
                'cate': good_data.cate_id
            }
        })

class GoodImgs(APIView):
    def get(self,request,id):
        # 判断商品是否存在
        try:
            good_data = Goods.objects.get(id=id)
        except Exception as e:
            print(e)
            return Response({'code': 400, 'msg': '商品不存在'})
        # 根据商品 反向查询对应的图片
        imgs_data = good_data.goodimg_set.all()
        # 手动序列化
        imgs_list = []
        for i in imgs_data:
            imgs_list.append({
                'id':i.id,
                'img':i.img,
                'title':i.title,
                'good':i.good_id,   #使用图片所属的商品id
            })
        return Response({'code':200,'msg':'查询成功','imgs':imgs_list})

from user.models import User
import redis
class HistoryView(APIView):
    # 添加历史记录 动态参数id:商品id
    def post(self,request,id):
        # 1.判断用户是否登录
        if request.user_info:
            uid = request.user_info.get('uid')  #解析用户信息中的 用户id uid
            user = User.objects.get(id=uid)     #根据用户id 查询用户信息ORM对象
        else:
            return Response({'code':400,'msg':'用户未登录'})
        # 2.添加历史记录
        key = 'history_%s' % user.id   #键
        r = redis.Redis(host='localhost',port=6379,db=5)  #链接redis
        r.lpush(key,id)   #将商品id  添加到历史记录中
        r.close()
        return Response({'code':200,'msg':'添加历史记录成功'})

class CollectView(APIView):
    # 添加收藏
    def post(self,request):
        # 1.判断用户是否登录
        if request.user_info:
            uid = request.user_info.get('uid')  #解析用户信息中的 用户id uid
            user = User.objects.get(id=uid)     #根据用户id 查询用户信息ORM对象
        else:
            return Response({'code':400,'msg':'用户未登录'})
        # 2.提取要收藏的商品id
        product_id = request.data.get('productID')
        # 3.给用户添加收藏，就是往mysql数据库添加数据
        GoodsCollect.objects.create(user_id=uid,goods_id=product_id)
        return Response({'code':200,'msg':'添加收藏成功'})
    # 查看收藏
    def get(self,request):
        # 1.判断用户是否登录
        if request.user_info:
            uid = request.user_info.get('uid')  # 解析用户信息中的 用户id uid
            user = User.objects.get(id=uid)  # 根据用户id 查询用户信息ORM对象
        else:
            return Response({'code': 400, 'msg': '用户未登录'})
        # 2.获取用户的收藏信息
        collects_data = GoodsCollect.objects.filter(user_id=user.id)
        # 3.序列化数据返回
        collect_list = []
        for i in collects_data:
            collect_list.append({
                'id':i.goods_id,  #商品id
                'img':i.goods.img,
                'sku_name':i.goods.sku_name,
                'title':i.goods.title,
                'selling_price':i.goods.selling_price,
                'price':i.goods.price,
            })
        return Response({'code':200, 'msg':'查看收藏成功', 'collect':collect_list})
    # 删除收藏
    def delete(self,request):
        # 1.判断用户是否登录
        if request.user_info:
            uid = request.user_info.get('uid')  # 解析用户信息中的 用户id uid
            user = User.objects.get(id=uid)  # 根据用户id 查询用户信息ORM对象
        else:
            return Response({'code': 400, 'msg': '用户未登录'})
        # 2.提取要删除的商品id
        product_id = request.data.get('productID')
        # 3.根据商品id 删除收藏
        GoodsCollect.objects.filter(goods_id=product_id,user_id=user.id).delete()
        return Response({'code': 200, 'msg': '删除成功'})

class CartView(APIView):
    #删除购物车
    def delete(self,request):
        #1.判断用户是否登录
        if request.user_info:
            user_id=request.user_info.get('uid')
            user=User.objects.get(id=user_id)
        else:
            return Response({'code':400,'msg':'用户未登录'})
        # 2.提取要更新的 商品id 和  商品数据
        product_id = request.data.get('productID')
        # 3.链接redis数据库，更新购物车数据
        cart_key = 'cart_%s' % user.id  # 获取购物车的键
        cart_select_key='cart_select_%s' %user.id  #获取选中项的键
        r = redis.Redis(host='localhost', port=6379, db=5)
        r.hdel(cart_key,product_id)     #删除购物车
        r.srem(cart_select_key,product_id)    #删除选中项
        return Response({'code': 200, 'msg': '删除成功'})



    #修改购物车商品数量
    def put(self,request):
        #1.判断用户是否登录
        if request.user_info:
            user_id=request.user_info.get('uid')
            user=User.objects.get(id=user_id)
        else:
            return Response({'code':400,'msg':'用户未登录'})
        #2.提取要更新的 商品id 和  商品数据
        product_id=request.data.get('productID')
        num=request.data.get('num')
        #3.链接redis数据库，更新购物车数据
        cart_key='cart_%s'%user.id   #获取购物车的键
        r=redis.Redis(host='localhost',port=6379,db=5)
        r.hset(cart_key,product_id,num)
        r.close()
        return Response({'code': 200, 'msg': '更新购物车数量成功'})
    # 加入购物车
    def post(self,request):
        # 1.列表用户是否登录
        if request.user_info:
            user_id = request.user_info.get('uid')
            user = User.objects.get(id=user_id)
        else:
            return Response({'code':400,'msg':'用户未登陆'})
        # 2.获取要加入商品id 并根据id获取商品
        product_id = request.data.get('productID')
        good_data = Goods.objects.get(id=product_id)
        # 3.判断库存是否大于0，如果库存小于0，返回库存不足
        if good_data.stock <= 0:
            return Response({'code':401,'msg':'库存不足'})
        # 4.判断该用户的购物车是否有商品
        # 拼接：购物车的键， 选中商品的键
        cart_key = 'cart_%s' % user_id
        cart_select_key = 'cart_select_%s' % user_id
        # 链接redis数据库，获取购物车数据
        r = redis.Redis(host='localhost',port=6379,db=5)
        num = r.hget(cart_key,product_id)    #获取商品的数量 需要解码
        if num:      #如果已有，在库存充足的情况下，数量加1 返回数量加1的响应
            num = int(num.decode())  # 解码 并转换成int类型
            if good_data.stock <= num:    #库存小于等于 购物车的数量
                r.close()
                return Response({'code':402,'msg':'购买数量已达上限'})
            else:   #数量充足 接着买 +1
                r.hset(cart_key,product_id,str(num+1))    #添加购物车
                r.sadd(cart_select_key,product_id)        #加购商品  默认是选中的
                r.close()
                return Response({'code':201,'msg':'购买数量+1'})
        else:            #如果没有，加入购物车，返回加入购物车成功响应
            r.hset(cart_key,product_id,'1')     #添加购物车
            r.sadd(cart_select_key,product_id)
            return Response({
                'code': 200,
                'msg': '添加购物车成功',
                'shoppingCartData': {
                    'id': cart_key,  # 购物车id， 如cart_1
                    'productID': product_id,  # 商品id
                    'productName': good_data.sku_name,  # 商品名称
                    'productImg': good_data.img,  # 商品图片
                    'price': good_data.price,  # 商品价格
                    'num': 1,  # 购物车中该商品数量
                    'maxNum': good_data.stock,  # 商品限购数量，即库存
                    'check': True  # 是否勾选
                }
            })
    # 展示购物车
    def get(self,request):
        # 1.列表用户是否登录
        if request.user_info:
            user_id = request.user_info.get('uid')
            user = User.objects.get(id=user_id)
        else:
            return Response({'code': 400, 'msg': '用户未登陆'})
        # 2.获取当前用户的购物车数据
        cart_key = 'cart_%s' % user_id     #购物车的键
        cart_select_key = 'cart_select_%s' % user_id    #选中项的键
        r = redis.Redis(host='localhost',port=6379,db=5)
        cart_goods = r.hgetall(cart_key)   #获取购物车数据
        cart_select = r.smembers(cart_select_key)   #获取购物车的选中项
        r.close()
        # 3.序列化购物车数据
        cart_list = []     #用于存放序列化后的结果
        for k, v in cart_goods.items():
            good_data = Goods.objects.get(id=int(k.decode()))    #查询购物车中的商品对象
            cart_list.append({
                'id': cart_key,  # 购物车id， 如cart_1
                'productID': good_data.id,  # 商品id
                'productName': good_data.sku_name,  # 商品名称
                'productImg': good_data.img,  # 商品图片
                'price': good_data.price,  # 商品价格
                'num': int(v.decode()),  # 购物车中该商品数量
                'maxNum': good_data.stock,  # 商品限购数量，即库存
                'check': k in cart_select  # 是否勾选
            })
            # 返回响应
        return  Response({'code':200,'msg':'获取购物车成功','cart':cart_list})

class SelectOne(APIView):
    #单选与取消单选
    def put(self,request):
        #1.判断用户是否登录
        if request.user_info:
            #user_info 是中间件从前端的请求头的token获取
            user_id=request.user_info.get('uid')
            user=User.objects.get(id=user_id)
        else:
            return Response({'code': 400, 'msg': '用户未登录'})
        #2.选取选中的商品id 和选中状态
        produce_id=request.data.get('productID')   #商品id
        status=request.data.get('status')           #状态
        #3.连接redis数据库，选中或取消选中商品
        #判断status  添加  或者删除 集中数据、
        cart_select_key='cart_select_%s' %user_id
        r=redis.Redis(host='localhost',port=6379,db=5)
        if status:
            r.sadd(cart_select_key,produce_id)
        else:
            r.srem(cart_select_key,produce_id)
        return Response({'code': 200, 'msg': '操作成功'})

class SelectAll(APIView):
    #全选与取消全选
    def put(self,request):
        #1.判断用户是否登录
        if request.user_info:
            #user_info是中间件 从前端的请求头中的token获取
            user_id=request.user_info.get('uid')
            user=User.objects.get(id=user_id)
        else:
            return Response({'code': 400, 'msg': '用户未登录'})
        #2.提取前端传递的状态
        status=request.data.get('status')
        #3.连接redis数据库，实现全选与取消全选
        r=redis.Redis(host='localhost',port=6379,db=5)
        cart_key='cart_%s'%user.id
        cart_select_key='cart_select_%s'%user_id
        if  status:
            #全选
            goods_id=r.hkeys(cart_key)    #获取购物车中的全部商品id
            for i in goods_id:            #循环 将购物车中的商品id一个一个存入到选中项中
                r.sadd(cart_select_key,str(i.decode()))
        else:
            #取消全选
            r.delete(cart_select_key)     #删除选中项
        r.close()
        return Response({'code': 200, 'msg': '操作成功'})